home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGNG_C
/
DBTOOLC.LZH
/
SOURCE.ARC
/
DBFIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1986-06-30
|
10KB
|
347 lines
/*
* NAME:
* finance.c
*
* SYNOPSIS:
* fv(pmt, rate, term) -- future value function
* pv(pmt, rate, term) -- present value function
* npv(pmt, flows, n) -- net present value function
* pmt(prin, rate, term) -- amortized payment function
* amort(prin, rate, n1, n2) -- amortization function
* sf(amt, rate, n) -- sinking fund function
* irr(guess, flows, n) -- internal rate of return
* mirr(risky, safe, flows, n) -- modified irr
*
* DESCRIPTION:
* 'Low level' financial functions for dBASE library. All are
* called by a jacketed routine from the main program pak.
*
* RETURNS:
* All functions return the actual result of the calculation as
* a double precision floating point value.
*
* AUTHOR: J. T. Cooper
*/
#include <stdio.h>
#ifdef AZTEC
#include "math.h"
double atof();
double atol();
#else
#include <dos.h>
#include <math.h>
#endif
/*
* NAME: fv - future value function
*
* SYNOPSIS:
* double fv(pmt, rate, term)
* double pmt; -- regular, periodic payment amount
* double rate; -- interest rate per period
* int term; -- number of periods
*
* DESCRIPTION:
* Calculates future (compounded) value of an annuity (ie,
* equal, regular payments) at a set interest rate for a
* given number of periods, according to the following formula:
*
* pmt * ((1 + rate)^term - 1)
* fv(pmt, rate, term) = ---------------------------
* rate
*
* RETURNS:
* Returns the future value.
*/
double fv(pmt, rate, term)
double pmt, rate;
int term;
{
return(pmt * (pow(1.0 + rate, (double)term) - 1.0)/rate);
}
/*
* NAME:
* pv - present value function
*
* SYNOPSIS:
* double pv(pmt, rate, term)
* double pmt; -- amount of regular payment (deposit)
* double rate; -- interest rate per period
* int term; -- number of periods
*
* DESCRIPTION:
* Calculates present value of an annuity at a set interest
* rate for the given number of periods, using the formula:
*
* pmt * (1 - 1/((1+rate)^term))
* pv(pmt, rate, term) = ------------------------------
* rate
*
* RETURNS:
* Returns the present value as a double precision floating
* point variable.
*
*/
double pv(pmt, rate, term)
double pmt, rate;
int term;
{
return(pmt * ((1.0 - pow(1.0 + rate, (double)(-term)))/rate));
}
/*
* NAME:
* npv - net present value function
*
* SYNOPSIS:
* double npv(rate, flows, n)
* double rate; -- interest rate per period
* double flows[]; -- list (array) of cash flows
* int n; -- # of payments to expect
*
* DESCRIPTION:
* Using the given discount rate, npv sums the present
* value of the cash flows; ie,
*
* npv(rate,flows,n) = sum of all (flows[i]/(1+rate)^i)
* where i ranges from 0 to n.
*
* RETURNS:
* Returns the net present value of the cash flows as a
* double precision floating point variable.
*
*/
double npv(rate, flows, n)
double rate; /* interest rate per period */
double flows[]; /* array of double precision variables */
int n; /* # of payments to expect */
{
double result;
result = 0.0;
while (n--)
result += flows[n]/pow(1.0 + rate, (double)n);
return(result);
}
/*
* NAME:
* pmt - calculate amortized payment
*
* SYNOPSIS:
* double(prin, rate, term)
* double prin; -- principal balance of a loan
* double rate; -- interest per period
* int term; -- number of periods
*
* DESCRIPTION:
* Calculates the constant, regular payments (made at the end
* of each period) needed to fully pay off a loan of the given
* amount (prin), rate, and term:
* rate
* pmt(prin, rate, term) = prin * --------------------
* 1 - 1/(1+rate)^term
* RETURNS:
* Returns the payment amount as a double precision floating
* point number.
*
*/
double pmt(prin, rate, term)
double prin; /* principal balance of a loan */
double rate; /* interest rate per pmt (!= 0) */
int term; /* number of periods */
{
return(prin / ((1.0 - pow(1.0 + rate, (double)(-term)))/rate));
}
/*
* NAME:
* amort - amortization function
*
* SYNOPSIS:
* double amort(prin, rate, n1, n2)
* double prin; -- principal amount of loan
* double rate; -- interest rate per period
* int n1; -- total number of periods
* int n2; -- number of payments completed
*
* DESCRIPTION:
* Calculates the amount of loan principal still outstanding
* after a given number of payments:
*
* 1 - 1/(1+rate)^(n1-n2)
* amort(prin,rate,n1, n2) = prin * ----------------------
* 1 - 1/(1+rate)^n1
* RETURNS:
* Returns the amortized amount as a double precision floating
* point variable.
*
*/
double amort(prin, rate, n1, n2)
double prin, /* principal */
rate; /* interest rate per period */
int n1, /* total # of periods */
n2; /* payments completed */
{
return(prin * ((1.0 - (1.0/(pow(1.0 + rate, (double)(n1 - n2))))) /
(1.0 - (1.0/(pow(1.0 + rate, (double) n1))))));
}
/*
* NAME:
* sf - sinking fund function
*
* SYNOPSIS:
* double sf(amt, rate, n)
* double amt; -- amount to be accumulated
* double rate; -- interest rate per period
* int n; -- total number of deposits to be made
*
* DESCRIPTION:
* Calculates the deposit required at the end of each period
* which would be necessary to accumulate a given amount,
* assuming a given interest rate and term:
* rate
* sf(amt, rate, n) = amt * --------------
* (1+rate)^n - 1
*
* RETURNS:
* Returns the deposit amount as a double precision floating
* point number.
*/
double sf(amt, rate, n)
double amt, /* amount to be accumulated */
rate; /* interest rate per period */
int n; /* total # of deposits */
{
return(amt * (rate / (pow(1.0 + rate, (double) n) - 1.0)));
}
/*
* NAME:
* irr - internal rate of return function
*
* SYNOPSIS:
* double irr(guess, flows, n)
* double guess; -- initial guess
* double flows[]; -- list (array) of cash flows
* int n; -- total number of periods
*
* DESCRIPTION:
* Approximates the interest rate which equates the present
* value of cash outflows and inflows; ie, the rate at which
* the present value of flows would be 0. Uses a home-brew
* algorithm which converges on a result using the initial guess
* as a starting point, and which seems to come reasonably
* close to those values obtained by Framework.
*
* RETURNS:
* Returns the net present value of flows as a double precision
* floating point number.
*
* NOTES:
* No confirmation of the algorithm used could be found; rather,
* empirical data has been used to establish its soundness.
*
*/
double irr(guess, flows, n)
double guess; /* initial guess */
double flows[]; /* array of double precision variables */
int n; /* # of periods to expect */
{
double zero; /* solution should approach 0.00 */
double high, low; /* will converge using these limits */
int cnt = 0;
int i;
int p;
double div;
#define MAXIRRITER 30 /* Max # of iterations */
high = (guess > 0 ? guess + 1.0 : 1.0);
low = (guess <= 1 ? guess -1.0 : 0.0);
do
{
i = n;
zero = 0.0;
while (i--)
{
div = 1.0;
for (p = i; p; p--)
div *= (1.0 + guess);
zero += flows[i]/div;
}
if (zero > 0.0)
low = guess;
else
high = guess;
guess = (high - low)/2.0 + low;
++ cnt;
} while (cnt < MAXIRRITER && zero != 0.0);
/* (zero == EACTLY 0.0 is unlikely) */
return(guess);
}
/*
* NAME:
* mirr - modified internal rate of return
*
* SYNOPSIS:
* double mirr(r, s, flows, n)
* double r; -- 'risky' rate at which outlays are financed
* double s; -- 'safe' rate at which revenues are invested
* double flows[]; -- list (array) of cash flows
* int n; -- total number of cash flows
*
* DESCRIPTION:
* Calculates the rate of return for an investment given the
* rate of return for future positive cash flows and the rate
* at which future cash outlays are to be discounted:
*
* npv(r, positive flows)(1+r)^n
* mirr(r,s,flows,n) = { ----------------------------- }^(1/n) - 1
* -npv(s, negative flows)
* RETURNS:
* Returns the modified internal rate of return as a double
* precision floating point number.
*
*/
double mirr(r, s, flows, n)
double r; /* 'risky' rate at which outlays are financed */
double s; /* 'safe' rate at which revenues are invested */
double flows[]; /* list of cash flows */
int n; /* # of cash flows */
{
double npvneg = 0.0; /* net present value of negative cash flows */
double npvpos = 0.0; /* npv of positive cash flows */
int i;
for (i = 0; i < n; i++)
{
if (flows[i] > 0)
npvpos += flows[i]/pow(1.0 + r, (double)i);
else
npvneg += flows[i]/pow(1.0 + s, (double)i);
}
return( pow((npvpos * pow((1.0+r),(double)(n-1))) / -npvneg,
1.0/(double)(n-1)) - 1.0);
}